home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
c
/
kernel.arc
/
K4.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-11-25
|
14KB
|
499 lines
;Listing 4 High Resolution Clock
;(C) Copyright 1986 Ken Berry.
;All rights reserved.
;Copies may be made for non-commercial, private use only.
;
include tele.mac ; system defintions (listing 2)
extrn t_syxtm:word ; system execution time accumulator
extrn sys_dgrp:word ; data segment storage
extrn sys_stat:word ; original register block
public t__tick ; system tick interrupt service
public t_astrm ; application task termination flag
public tmr_dspl ; physical display pointer
public tmr_dvsr ; timer period
public tmr_ilck ; tick service reentrant interlock
public tmr_sync ; synchronization function address
public tmr_tkct ; tick clock
public tmr_xtm ; tick service execution time
public tmr__clr ; reset time base generation
public tmr__int ; timer initialization function
public tmr__rst ; timer termination function
public tmr__sts ; read timer status
public tmr__tmr ; restart hardware timer
public t_rdclk ; read high resolution clock
public t_rtactg ; psuedo time accumulator pointer
public t_rtmark ; mark execution interval
public t__rdclk ; read real time clock
public td_ref ; clock update tick reference count
public td_tct ; clock tick timer
public td__set ; set time of day clock
public td__upd ; update time of day clock
public w__cdspl ; physical display update function
public w__sync ; physical display synchronization
RLCINT equ 80h ; relocated alternate time base interrupt
TMRINT equ 8 ; hardware timer interrupt
TMRPRT equ 40h ; timer (8253) port
TMRPRD equ 19912 ; timer period (60 Hz rate)
;TMRPRD equ 9956 ; timer period (120 Hz rate)
INTPRT equ 20h ; interrupt controller (8259) port
TMRMSK equ 01h ; hardware timer interrupt mask
INTEOI equ 20h ; interrupt termination value
DSPCT equ 1 ; 60 Hz interrupt rate
;DSPCT equ 2 ; 120 Hz interrupt rate
IDV0 equ 3 ; tmr_idv0 divisor
ISKP0 equ 776 ; tmr_ict correction value
ISKP1 equ 11 ; tmr_idv1 correction value
ISKP2 equ 38 ; tmr_idv2 correction value
dseg
tmr_tkct dw 0 ; interrupt counter
tmr_dct db 0 ; display counter
tmr_ict dw 0 ; tick clock (for time base generation)
tmr_dvsr dw TMRPRD ; 1/2 timer period
t_astrm db 0FFh ; application task termination flag
tmrflg db 0FFh ; system state flag (t__tick)
tmr_ilck db 0 ; tick service reentrant interlock
tmr_idv0 db 0 ; clock time base generator
tmr_idv1 db 0 ; primary alternate time base generator
tmr_idv2 db 0 ; secondary alternate time base generator
tmr_dspl dw 0 ; console display w_pwdw pointer
t_rtactg dw 0 ; psuedo time accumulator pointer
t_rtrfct dw 0 ; real time reference count
t_rttick dw 0 ; tick clock phase
tmr_xtm dw 3 dup (0) ; tick service psuedo time accumulator
tmrpxtm dw 0 ; prior psuedo time accumulator pointer
tmr_sync dw offset pgroup:w__sync ; synchronization function pointer
td_ref dw 0 ; clock update tick reference count
td_tct dw 0 ; clock tick timer
endds
pseg
;t__tick system tick service
;
;t__tick\\
;
;Control only comes here in response to an interrupt from the system clock.
;This function serves three purposes. It maintains the system clock, which
;provides the current date and time for both system and application uses. It
;also performs an update of the first physical display. And finally it
;terminates the execution interval for the current application task.
;
t__tick proc far
; reentrant lockout
assume ss:nothing,ds:nothing,es:nothing
sti ; interrupts on
push ds ; protect ds
push ax ; protect ax
mov ax,dgroup ; establish data addressability
mov ds,ax
assume ds:dgroup
mov al,INTEOI ; terminate interrupt
out INTPRT,al
ilck al,tmr_ilck ; test for not reentrant call
or al,al
jz tick
pop ax ; restore ax
pop ds ; restore ds
iret ; return from interrupt
; system interlock
tick: mov t_astrm,0FFh ; terminate application task
sys_entr tmrflg ; enter system state
; set machine environment
sys_sctx ; save processor context
push bp ; protect bp
mov bp,sp ; mark stack location
lea ax,tmr_xtm ; accumulate psuedo time
push ax
call t_rtmark
mov sp,bp
mov tmrpxtm,ax ; store prior pointer
; real time system processing
inc tmr_dct ; remove display harmonics
mov al,DSPCT
xor al,tmr_dct
jnz tick4
mov tmr_dct,al
push tmr_dspl ; display physical window
call w__cdspl
mov sp,bp ; restore stack pointer
inc tmr_ict ; increment interrupt counter
inc tmr_tkct ; increment tick clock
; time base generation
mov ax,ISKP0 ; long term time base correction
xor ax,tmr_ict
jnz tick1
mov tmr_ict,ax
call tick5 ; update system tick clock
tick1: inc tmr_idv0 ; generate clock time base
mov al,IDV0
xor al,tmr_idv0
jnz tick3
mov tmr_idv0,al
call tick5 ; update system tick clock
inc tmr_idv1 ; primary alternate time base correction
mov al,ISKP1
xor al,tmr_idv1
jnz tick2
mov tmr_idv1,al
int RLCINT ; update alternate time base
inc tmr_idv2 ; secondary alternate time base correction
mov al,ISKP2
xor al,tmr_idv2
jnz tick2
mov tmr_idv2,al
int RLCINT ; update alternate time base
tick2: int RLCINT ; update alternate time base
; terminate interrupt service
tick3: push tmrpxtm ; restore original psuedo time accumulator
call t_rtmark
mov sp,bp
pop bp ; restore bp
test tmrflg,0FFh ; test for interrupted system task
jnz tick4
xor ax,ax ; terminate task
mov tmr_ilck,al ; enable reentrance
retn ; near return to system task management
tick4: sys__rctx ; restore processor context
cli ; interrupts off
mov tmr_ilck,0 ; enable reentrance
pop ds ; restore ds
iret ; return to interrupted task
; update system tick counter
tick5: mov ax,td_tct ; test for no overflow
inc ax
cmp ax,td_ref
jne tick6
call td__upd ; update clock
xor ax,ax ; reset tick counter
mov td_ref,ax
mov td_tct,ax
tick6: inc td_tct ; increment tick counter
retn ; return
t__tick endp
;tmr__int initialize timer
;
;tmr__int()
;
;All data areas necessary for clock maintenance are initialized. The hardware
;timer is programmed for the appropriate rate and its interrupt vector is made
;to point to sys_tmr. The original vector is relocated and will be used by
;sys_tmr as the alternate time base.
;
tmr__int proc near
call tmr__dsi ; diable interrupts
mov ax,dgroup ; set data segment
mov sys_dgrp,ax
mov ax,cs ; set code segment
lea si,sys_stat
mov [si].rcs,ax
cli ; interrupts off
mov tmr_ilck,0FFh ; lockout t__tick
mov bx,tmr_sync ; test for no synchronization function
test bx,bx
jz int0
lea bx,tmr_sync ; synchronize timer interrupt
call [bx]
jmp short int1 ; continue
int0: call tmr__tmr ; start timer
int1: call t_rdclk ; set real time clock phase
mov t_rttick,ax
mov t_rtrfct,ax ; set reference count
mov t_rtactg,offset dgroup:t_syxtm ; initialize time accumulator
call td__set ; set current time
sti ; interrupts on
xor ax,ax ; form 0
push ds ; protect ds
mov ds,ax ; relocate original interrupt vector
mov di,ax
cli
mov ax,[di+4*TMRINT]
mov [di+4*RLCINT],ax
mov ax,[di+4*TMRINT+2]
mov [di+4*RLCINT+2],ax
mov ax,offset pgroup:t__tick ; set interrupt service
mov [di+4*TMRINT],ax
mov ax,cs
mov [di+4*TMRINT+2],ax
sti ; interrupts on
pop ds ; restore ds
call tmr__eni ; enable interrupts
ret ; return
tmr__int endp
;
;tmr__clr reset time base generation
;
;tmr__clr()
;
;The time base adjustment variables are reset. This function is to be called by
;td__set when the time of day is initially set from a continuous clock. Nothing
;is returned.
;
tmr__clr proc near
xor ax,ax ; zero time base generation variables
mov tmr_idv0,al
mov tmr_idv1,al
mov tmr_idv2,al
ret ; return
tmr__clr endp
;tmr__rst reset timer
;
;tmr__rst()
;
;The original interrupt service routine is restored and the hardware clock is
;reprogrammed. However, the original hardware values are not available in this
;edition. Therefore the original system state cannot always be restored.
;
tmr__rst proc near
mov tmr_ilck,0FFh ; lock out interrupt service
push ds ; protect ds
xor ax,ax ; restore original interrupt vector
mov ds,ax
mov di,ax
call tmr__dsi ; disable timer interrupt
cli ; interrupts off
mov ax,[di+4*RLCINT]
mov [di+4*TMRINT],ax
mov ax,[di+4*RLCINT+2]
mov [di+4*TMRINT+2],ax
pop ds ; restore ds
xor bx,bx ; restart hardware timer
call tmr__str
sti ; interrupts on
call tmr__eni ; enable timer interrupt
ret ; return
tmr__rst endp
;tmr__tmr restart hardware timer
;
;tmr__tmr\\
;
;Channel 0 of an 8253 timer is initialized to mode 3. The count in bx is then
;programmed.
;
tmr__tmr proc near ; restart timer
mov bx,tmr_dvsr ; set tele system tick period
tmr__str proc near ; set timer period
mov al,20 ; reset 8253 (mode 0, count >= 8,192)
out TMRPRT+3,al ; [> 6.8 msec]
iowait
out TMRPRT,al
mov al,36h ; initialize 8253 (mode 3, both bytes)
iowait
out TMRPRT+3,al
mov al,bl
iowait
out TMRPRT,al
mov al,bh
iowait
out TMRPRT,al
ret ; return
tmr__str endp
tmr__tmr endp
;tmr__sts read timer status
;
;tmr__sts()
;
;The returned value is the current count in the timer.
;
tmr__sts proc near ; read timer status
mov al,00h ; set read mode
out TMRPRT+3,al
nop ; allow timer chip to recover
in al,TMRPRT ; read count
mov ah,al
in al,TMRPRT
xchg ah,al
ret ; return
tmr__sts endp
;
;tmr__dsi disable interrupt
;
;tmr__dsi()
;
;The timer interrupt is disabled at the 8259 interrupt controller.
;
tmr__dsi proc near
cli ; interrupts off
in al,INTPRT+1 ; disable timer interrupt
or al,TMRMSK
iowait
out INTPRT+1,al
sti ; interrupts on
ret ; return
tmr__dsi endp
;tmr__eni enable interrupt
;
;tmr__eni()
;
;The timer interrupt is enabled at the 8259 interrupt controller.
;
tmr__eni proc near
cli ; interrupts off
in al,INTPRT+1; ; enable timer interrupt
and al,not TMRMSK
iowait
out INTPRT+1,al
sti ; interrupts on
ret ; return
tmr__eni endp
;
;t_rdclk read real time clock
;
;t_rdclk()
;
;The current value of the real time clock is read and returned.
;
DMAREG equ 0 ; refresh address DMA register
t_rdclk proc near
rdclk0: mov dx,DMAREG ; set DMA register address
call t__rdclk ; read time
mov bx,ax ; store time
call t__rdclk ; read time again
cmp ah,bh ; test for interruption
jne rdclk0
ret ; return
t_rdclk endp
t__rdclk proc near
cli ; interrupts off
in al,dx ; read time
mov ah,al
iowait
in al,dx
xchg al,ah
sti ; interrupts on
ret ; return
t__rdclk endp
;t_rtmark mark execution interval
;
;t_rtmark(np)
;pointer *np;
;
;The number of refreshes since the last call to t_rtmark is accumulated. Then
;the reference count is reset. np points to the area that will accumulate the
;number of refreshes to the next call. The returned value is the original
;accumulator pointer.
;
t_rtmark proc near
push bp ; protect bp
mov bp,sp ; establish parameter addressability
call tmr__dsi ; disable timer interrupt
call t_rdclk ; read real time clock
mov bx,ax ; protect current count
xchg bx,t_rtrfct ; update reference count
sub ax,bx ; compute execution interval
jnc mark1 ; test for no overflow
neg ax ; adjust count
mark1: mov bx,t_rtactg ; accumulate execution time
add ax,[bx]
mov [bx],ax
jnc markxit
add word ptr [bx+2],1
jnc markxit
inc word ptr [bx+4]
markxit: mov ax,bx ; return orginal pointer
mov bx,[bp].t_np0 ; set new accumulator pointer
mov t_rtactg,bx
call tmr__eni ; enable timer interrupt
pop bp ; restore bp
ret ; return
t_rtmark endp
;w__cdspl display physical buffer
;
;w__cdspl(pw)
;struct w_phys *pw;
;
;Physical window pw is displayed. This function is called by the system tick
;clock interrupt service function. Nothing is returned.
;
w__cdspl proc near
ret ; return
w__cdspl endp
;
;w__sync synchronize interrupt to display
;
;w__sync()
;
;The system tick clock timer is adjusted so that w__dsply executes just prior
;to the vertical blanking interval. Nothing is returned.
;
w__sync proc near
call tmr__tmr ; start timer
w__sync endp
;
;td__set set time of day clock
;
;td__set()
;
;The clock is set to the current time. Nothing is returned.
;
td__set proc near
ret ; return
td__set endp
;
;td__upd update clock
;
;td__upd()
;
;The clock is updated based on the number of ticks since it was last updated.
;The normal return (ax) is _F. _E is returned if the call was locked out.
;
td__upd proc near
ret ; return
td__upd endp
endps
end